package notify

import (
	"context"
	"errors"
	"fmt"
	"wxpay/pkg/mcontext"
	"wxpay/pkg/merrors"

	"go.uber.org/zap"
)

type PostMan struct {
	L Letter
}

func (pm PostMan) Notify() {
	if pm.L.RequireNotification() {
		pm.L.Notify()
		pm.L.Dump("error")
	} else {
		pm.L.Dump("info")
	}
}

type Letter interface {
	// 根据错误类型决定是否发送企业微信
	RequireNotification() (required bool)
	Notify()
	Dump(level string)
}

type SystemErrorWechatNotify struct {
	Ctx context.Context
	Err error
	Env string
}

func (e SystemErrorWechatNotify) RequireNotification() (required bool) {
	if e.Err != nil {
		switch v := e.Err.(type) {
		case *merrors.Error:
			switch root := v.Cause().(type) {
			case *merrors.Error:
				// 客户端取消请求造成context.Canceled不用触发错误通知
				if errors.Is(root.Err, context.Canceled) {
					required = false
					return
				}
				should, ok := merrors.ErrorsShouldNotify[root.Kind]
				if ok && should {
					required = true
				}
			default:
				required = true
			}
		default:
			required = true
		}
	}
	return
}

func (e SystemErrorWechatNotify) Notify() {
	// 发送企业微信
	if err := SendMarkDown(fmt.Sprintf("[%s]wxpay服务系统错误，请及时处理\n**request_id**: %s \n**err**:%s", e.Env, mcontext.GetRqId(e.Ctx), e.Err.Error())); err != nil {
		return
	}
}

func (e SystemErrorWechatNotify) Dump(level string) {
	// 写本地日志
	log := mcontext.Logger(e.Ctx)
	if e.Err != nil {
		switch level {
		case "info":
			log.Info("业务错误", zap.Error(e.Err))
		default:
			log.Error("系统错误", zap.Error(e.Err))
		}

	}
}
